﻿using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace GarminConnect
{
    public class OAuth1Client(string consumerKey, string consumerSecret, string token = "", string tokenSecret = "")
    {
        private readonly string consumerKey = consumerKey;
        private readonly string consumerSecret = consumerSecret;
        private readonly string token = token;
        private readonly string tokenSecret = tokenSecret;

        public string GenerateAuthorizationHeader(string httpMethod, string url, IDictionary<string, string> parameters)
        {
            var oauthParams = new SortedDictionary<string, string>
        {
            { "oauth_consumer_key", consumerKey },
            { "oauth_signature_method", "HMAC-SHA1" },
            { "oauth_timestamp", GenerateTimeStamp() },
            { "oauth_nonce", GenerateNonce() },
            { "oauth_version", "1.0" },
        };

            if (!string.IsNullOrEmpty(token))
            {
                oauthParams.Add("oauth_token", token);
            }

            // 合并请求参数和 OAuth 参数
            foreach (var param in parameters)
            {
                oauthParams.Add(param.Key, param.Value);
            }

            // 生成签名基字符串
            var signatureBaseString = GenerateSignatureBaseString(httpMethod, url, oauthParams);

            // 生成签名密钥
            var signingKey = $"{UrlEncode(consumerSecret)}&{UrlEncode(tokenSecret)}";

            // 计算签名
            var signature = ComputeHmacSha1(signingKey, signatureBaseString);

            oauthParams.Add("oauth_signature", signature);

            // 构造 Authorization 头
            var headerBuilder = new StringBuilder("OAuth ");
            foreach (var param in oauthParams)
            {
                if (param.Key.StartsWith("oauth_"))
                {
                    headerBuilder.AppendFormat("{0}=\"{1}\", ", param.Key, UrlEncode(param.Value));
                }
            }

            // 去掉最后的逗号和空格
            return headerBuilder.ToString().TrimEnd(',', ' ');
        }

        private static string GenerateNonce()
        {
            return new Random().Next(123400, 9999999).ToString();
        }

        private static string GenerateTimeStamp()
        {
            var secondsSinceEpoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
            return secondsSinceEpoch.ToString();
        }

        private static string GenerateSignatureBaseString(string httpMethod, string url, SortedDictionary<string, string> parameters)
        {
            var paramString = new StringBuilder();
            foreach (var param in parameters)
            {
                paramString.AppendFormat("{0}={1}&", UrlEncode(param.Key), UrlEncode(param.Value));
            }
            // 去掉最后一个 &
            paramString.Length--;

            return string.Format("{0}&{1}&{2}",
                httpMethod.ToUpper(),
                UrlEncode(url),
                UrlEncode(paramString.ToString()));
        }

        private static string ComputeHmacSha1(string key, string data)
        {
            using var hmac = new HMACSHA1(Encoding.ASCII.GetBytes(key));
            var hash = hmac.ComputeHash(Encoding.ASCII.GetBytes(data));
            return Convert.ToBase64String(hash);
        }

        private static string UrlEncode(string value)
        {
            return HttpUtility.UrlEncode(value)
                .Replace("+", "%20")
                .Replace("*", "%2A")
                .Replace("%7E", "~");
        }
    }

}
